package types

import (
	"strconv"
	"time"
)

type (
	Int    int
	Int8   int8
	Int16  int16
	Int32  int32
	Int64  int64
	Uint   uint
	Uint8  uint8
	Uint16 uint16
	Uint32 uint32
	Uint64 uint64
	// String string

	F32 struct {
		f         float32
		format    byte
		precision int
	}
	F64 struct {
		f         float64
		format    byte
		precision int
	}

	CommonError struct {
		e error
	}
	CommonTime struct {
		t      time.Time
		format string
	}
	Duration int64
)

// 类型转换调用和方法调用统一使用小括号。
// e.g.: Int(2), Float32(2.0), Time(time.Now())

func Float32(f float32) F32 { return F32{f, 'f', -1} }
func Float64(f float64) F64 { return F64{f, 'f', -1} }

func Float32f(f float32, format byte, precision int) F32 { return F32{f, format, precision} }
func Float64f(f float64, format byte, precision int) F64 { return F64{f, format, precision} }

func Error(e error) CommonError { return CommonError{e} }

const (
	defaultTimeFormat = "2006-01-02 15:04:05"
)

func Time(t time.Time) CommonTime                 { return CommonTime{t, defaultTimeFormat} }
func Timef(t time.Time, format string) CommonTime { return CommonTime{t, format} }

func Timestamp(t time.Time) Int64      { return Int64(t.Unix()) }
func TimestampMilli(t time.Time) Int64 { return Int64(t.UnixMilli()) }
func TimestampMicro(t time.Time) Int64 { return Int64(t.UnixMicro()) }
func TimestampNano(t time.Time) Int64  { return Int64(t.UnixNano()) }

func (i Int) AppendTo(b *ByteSlice)   { b.AppendInt64(int64(i)) }
func (i Int) String() string          { return strconv.FormatInt(int64(i), 10) }
func (i Int8) AppendTo(b *ByteSlice)  { b.AppendInt64(int64(i)) }
func (i Int8) String() string         { return strconv.FormatInt(int64(i), 10) }
func (i Int16) AppendTo(b *ByteSlice) { b.AppendInt64(int64(i)) }
func (i Int16) String() string        { return strconv.FormatInt(int64(i), 10) }
func (i Int32) AppendTo(b *ByteSlice) { b.AppendInt64(int64(i)) }
func (i Int32) String() string        { return strconv.FormatInt(int64(i), 10) }
func (i Int64) AppendTo(b *ByteSlice) { b.AppendInt64(int64(i)) }
func (i Int64) String() string        { return strconv.FormatInt(int64(i), 10) }

func (i Uint) AppendTo(b *ByteSlice)   { b.AppendUint64(uint64(i)) }
func (i Uint) String() string          { return strconv.FormatUint(uint64(i), 10) }
func (i Uint8) AppendTo(b *ByteSlice)  { b.AppendUint64(uint64(i)) }
func (i Uint8) String() string         { return strconv.FormatUint(uint64(i), 10) }
func (i Uint16) AppendTo(b *ByteSlice) { b.AppendUint64(uint64(i)) }
func (i Uint16) String() string        { return strconv.FormatUint(uint64(i), 10) }
func (i Uint32) AppendTo(b *ByteSlice) { b.AppendUint64(uint64(i)) }
func (i Uint32) String() string        { return strconv.FormatUint(uint64(i), 10) }
func (i Uint64) AppendTo(b *ByteSlice) { b.AppendUint64(uint64(i)) }
func (i Uint64) String() string        { return strconv.FormatUint(uint64(i), 10) }

func (f F32) AppendTo(b *ByteSlice) { b.AppendFloat32(f.f, f.format, f.precision) }
func (f F32) String() string        { return strconv.FormatFloat(float64(f.f), f.format, f.precision, 32) }
func (f F64) AppendTo(b *ByteSlice) { b.AppendFloat64(f.f, f.format, f.precision) }
func (f F64) String() string        { return strconv.FormatFloat(float64(f.f), f.format, f.precision, 64) }

func (e CommonError) AppendTo(b *ByteSlice) { b.data = append(b.data, []byte(e.e.Error())...) }
func (e CommonError) String() string        { return e.e.Error() }

func (t CommonTime) AppendTo(b *ByteSlice) { b.data = t.t.AppendFormat(b.data, t.format) }
func (t CommonTime) String() string        { return t.t.Format(t.format) }

func (d Duration) AppendTo(b *ByteSlice) { b.data = append(b.data, time.Duration(d).String()...) }
func (d Duration) String() string        { return time.Duration(d).String() }
